home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / OpenGL / lorenz / lorenz.c next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  17.4 KB  |  672 lines

  1. /*
  2.  * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED 
  4.  * Permission to use, copy, modify, and distribute this software for 
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that 
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission. 
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  * 
  25.  * US Government Users Restricted Rights 
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36.  */
  37. /*
  38.  * Lorenz Attractor Demo
  39.  *
  40.  * Adapted from code originally written for the 4D60GT by
  41.  * Aaron T. Ferrucci (aaronf@cse.ucsc.edu), 7/3/92.
  42.  *
  43.  * Description:
  44.  *
  45.  * This program shows some particles stuck in a Lorenz attractor (the parameters
  46.  * used are r=28, b=8/3, sigma=10). The eye is attracted to the red particle,
  47.  * with a force directly proportionate to distance. A command line
  48.  * puts the whole mess inside a box made of hexagons. I think this helps to
  49.  * maintain the illusion of 3 dimensions, but it can slow things down.
  50.  * Other options allow you to play with the redraw rate and the number of new
  51.  * lines per redraw. So you can customize it to the speed of your machine.
  52.  * 
  53.  * For general info on Lorenz attractors I recommend "An Introduction to
  54.  * the Lorenz Equations", IEEE Transactions on Circuits and Systems, August '83.
  55.  *
  56.  * Bugs: hidden surface removal doesn't apply to hexagons, and
  57.  * works poorly on lines when they are too close together.
  58.  *
  59.  * Notes on OpenGL port:
  60.  * 
  61.  * The timer functions do not exist in OpenGL, so the drawing occurs in a
  62.  * continuous loop, controlled by step, stop and go input from the keyboard.
  63.  * Perhaps system function could be called to control timing.
  64.  *
  65.  */
  66.  
  67. #define __EXTENSIONS__
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include <string.h>
  71. #include <GL/gl.h>
  72. #include <GL/glu.h>
  73. #include <math.h>
  74. #include <time.h>
  75. #include <getopt.h>
  76. #include "tk.h"
  77.  
  78.  
  79. static GLuint asphere;
  80.  
  81. #define POINTMASK (unsigned long)511
  82. #define G (0.002)    /* eyept to red sphere gravity */
  83. #define LG (0.3)
  84. #define CUBESIDE (120.)
  85. #define CUBESCALE (23.)
  86. #define CUBEOFFX (-4.)
  87. #define CUBEOFFY (0.)
  88. #define CUBEOFFZ (57.)
  89. #define FALSE 0
  90. #define TRUE 1
  91.  
  92. /* globals */
  93. float sigma = 10., r = 28., b = 8./3., dt = 0.003;
  94. unsigned long rp = 0, bp = 0, gp = 0, yp = 0, mp = 0;
  95. long xmax, ymax, zmax, zmin;
  96. float rv[POINTMASK+1][3],            /* red points */
  97.     bv[POINTMASK+1][3],        /* blue points */
  98.     gv[POINTMASK+1][3],        /* green points */
  99.     yv[POINTMASK+1][3],        /* yellow points */
  100.     mv[POINTMASK+1][3];        /* magenta points */
  101.  
  102. int lpf;                /* number of new lines per frame */
  103.  
  104. float eyex[3],    /* eye location */
  105.      eyev[3],    /* eye velocity */
  106.      eyel[3];    /* lookat point location */
  107. GLint fovy = 600;
  108. float dx, dy, dz;
  109. GLUquadricObj *quadObj;
  110.  
  111. float cubeoffx = CUBEOFFX;
  112. float cubeoffy = CUBEOFFY;
  113. float cubeoffz = CUBEOFFZ;
  114. float farplane = 80.;
  115.  
  116. int animate = 1;
  117.  
  118. /* option flags */
  119. GLboolean hexflag,        /* hexagons? */
  120.     sflag,             
  121.     fflag,            
  122.     wflag,
  123.     gflag,
  124.     debug;
  125.  
  126. /* option values */
  127. short hexbright;    /* brightness for hexagon color */
  128. int speed,        /* speed (number of new line segs per redraw) */
  129.     frame;        /* frame rate (actually noise value for TIMER0) */
  130. float a = 0,
  131.     da;            /* hexagon rotational velocity (.1 degree/redraw) */
  132. float gravity;
  133.  
  134. /* function declarations */
  135. void init_3d(void);
  136. void init_graphics(void);
  137. void draw_hexcube(void);
  138. void draw_hexplane(void);
  139. void draw_hexagon(void);
  140. void move_eye(void);
  141. void redraw(void);
  142. void next_line(float v[][3], unsigned long *p);
  143. void parse_args(int argc, char **argv);
  144. void print_usage(char*);
  145. void print_info(void);
  146. void sphdraw(float args[4]);
  147. void setPerspective(int angle, float aspect, float zNear, float zFar);
  148.  
  149.  
  150. static void Reshape(int width, int height)
  151. {
  152.  
  153.       glViewport(0,0,width,height);
  154.       glClear(GL_COLOR_BUFFER_BIT);
  155.       xmax = width;
  156.       ymax = height;
  157. }
  158.  
  159. static GLenum Key(int key, GLenum mask)
  160. {
  161.  
  162.     switch (key) {
  163.       case TK_ESCAPE:
  164.     gluDeleteQuadric(quadObj);
  165.     tkQuit();
  166.       case TK_g:
  167.     animate = 1;
  168.     break;
  169.       case TK_s:
  170.      animate = 0;
  171.      break;
  172.       default:
  173.     return GL_FALSE;
  174.     }
  175.     return GL_TRUE;
  176. }
  177.  
  178. static void Draw(void)
  179. {
  180.     int i, j;
  181.  
  182.     if (animate) {
  183.     i = speed;
  184.     while (i--) {
  185.         next_line(rv, &rp);
  186.         next_line(bv, &bp);
  187.         next_line(gv, &gp);
  188.         next_line(yv, &yp);
  189.         next_line(mv, &mp);
  190.     }
  191.     glPushMatrix();
  192.     move_eye();
  193.     redraw();
  194.     glPopMatrix();
  195.     }
  196. }
  197.  
  198. void main(int argc, char **argv)
  199. {
  200.  
  201.     parse_args(argc, argv);
  202.  
  203.     tkInitPosition(0, 0, 600, 600);
  204.  
  205.     tkInitDisplayMode(TK_RGB|TK_DOUBLE|TK_DIRECT);
  206.  
  207.     if (tkInitWindow("Lorenz Attractors") == GL_FALSE) {
  208.         tkQuit();
  209.     }
  210.  
  211.     init_3d();
  212.     init_graphics();
  213.  
  214.     /* draw the first POINTMASK points in each color */
  215.     while(rp < POINTMASK) {
  216.     next_line(rv, &rp);
  217.     next_line(bv, &bp);
  218.     next_line(gv, &gp);
  219.     next_line(yv, &yp);
  220.     next_line(mv, &mp);
  221.     }
  222.  
  223.     eyex[0] = eyex[1] = eyex[2] = 0.;
  224.     eyel[0] = rv[rp][0];
  225.     eyel[1] = rv[rp][1];
  226.     eyel[2] = rv[rp][2];
  227.     
  228.     glPushMatrix();
  229.     move_eye();
  230.     redraw();
  231.     glPopMatrix();
  232.  
  233.     tkExposeFunc(Reshape);
  234.     tkReshapeFunc(Reshape);
  235.     tkKeyDownFunc(Key);
  236.     tkIdleFunc(Draw);
  237.     tkExec();
  238. }
  239.  
  240. /* compute the next point on the path according to Lorenz' equations. */
  241. void next_line(float v[][3], unsigned long *p)
  242. {
  243.  
  244.     dx = sigma * (v[*p][1] - v[*p][0]) * dt;
  245.     dy = (r*v[*p][0] - v[*p][1] + v[*p][0]*v[*p][2]) * dt;
  246.     dz = (v[*p][0] *v[*p][1] + b*v[*p][2]) * dt;    
  247.     
  248.     v[(*p + 1) & POINTMASK][0] = v[*p][0] + dx;
  249.     v[(*p + 1) & POINTMASK][1] = v[*p][1] + dy;
  250.     v[(*p + 1) & POINTMASK][2] = v[*p][2] - dz;
  251.     *p = (*p + 1) & POINTMASK;
  252. }
  253.  
  254. void drawLines(unsigned long index, float array[POINTMASK][3])
  255. {
  256.     unsigned long p;
  257.     int i;
  258.  
  259. #define LINE_STEP 4
  260.  
  261.     p = (index+1)&POINTMASK;
  262.     i = LINE_STEP-(p % LINE_STEP);
  263.     if (i == LINE_STEP) i=0;
  264.     glBegin(GL_LINE_STRIP);
  265.     /* draw points in order from oldest to newest */
  266.     while(p != index) {
  267.         if (i == 0) {
  268.         glVertex3fv(array[p]);
  269.         i = LINE_STEP;
  270.         } 
  271.         i--;
  272.         p = (p+1) & POINTMASK;
  273.     }
  274.     glVertex3fv(array[index]);
  275.     glEnd();
  276. }
  277.  
  278. void redraw(void)
  279. {
  280.     unsigned long p;
  281.     
  282.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  283.  
  284.     if(hexflag)
  285.     draw_hexcube();
  286.  
  287.     glColor3f(1.0, 0.0, 0.0);
  288.     drawLines(rp, rv);
  289.     sphdraw(rv[rp]);
  290.  
  291.     glColor3f(0.0, 0.0, 1.0);
  292.     drawLines(bp, bv);
  293.     sphdraw(bv[bp]);
  294.     
  295.     glColor3f(0.0, 1.0, 0.0);
  296.     drawLines(gp, gv);
  297.     sphdraw(gv[gp]);
  298.  
  299.     glColor3f(1.0, 0.0, 1.0);
  300.     drawLines(yp, yv);
  301.     sphdraw(yv[yp]);
  302.  
  303.     glColor3f(0.0, 1.0, 1.0);
  304.     drawLines(mp, mv);
  305.     sphdraw(mv[mp]);
  306.  
  307.     tkSwapBuffers();
  308. }
  309.  
  310. void move_eye(void)
  311. {
  312.     /* first move the eye */
  313.     eyev[0] += gravity * (rv[rp][0] - eyex[0]);
  314.     eyev[1] += gravity * (rv[rp][1] - eyex[1]);
  315.     eyev[2] += gravity * (rv[rp][2] - eyex[2]);
  316.  
  317.     /* adjust position using new velocity */
  318.     eyex[0] += eyev[0] * dt;
  319.     eyex[1] += eyev[1] * dt;
  320.     eyex[2] += eyev[2] * dt;
  321.  
  322.     /* move the lookat point */
  323.     /* it catches up to the red point if it's moving slowly enough */
  324.     eyel[0] += LG * (rv[rp][0] - eyel[0]);
  325.     eyel[1] += LG * (rv[rp][1] - eyel[1]);
  326.     eyel[2] += LG * (rv[rp][2] - eyel[2]);
  327.  
  328.     /* change view */
  329.     gluLookAt(eyex[0], eyex[1], eyex[2], eyel[0], eyel[1], eyel[2],
  330.           0, 1, 0);
  331. }
  332.  
  333. void draw_hexcube(void)
  334. {
  335.  
  336.     a += da;
  337.     if(a >= 720.)        /* depends on slowest rotation factor */
  338.     a = 0.;
  339.  
  340.     /* draw hexplanes, without changing z-values */
  341.     glDepthMask(GL_FALSE); 
  342.     glDisable(GL_DEPTH_TEST);
  343.  
  344.     /* x-y plane */
  345.     glColor3f(0.2, 0.2, 0.6);
  346.     glPushMatrix();
  347.     glTranslatef(cubeoffx, cubeoffy, cubeoffz);
  348.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  349.     draw_hexplane();
  350.     glPopMatrix();
  351.  
  352.     /* x-y plane, translated */
  353.     glPushMatrix();
  354.     glTranslatef(cubeoffx, cubeoffy, cubeoffz - 2*CUBESIDE);
  355.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  356.     draw_hexplane();
  357.     glPopMatrix();
  358.  
  359.     glColor3f(0.6, 0.2, 0.2);
  360.     /* x-z plane, translate low */
  361.     glPushMatrix();
  362.     glRotatef(90, 1.0, 0.0, 0.0);
  363.     glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy + CUBESIDE);
  364.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  365.     draw_hexplane();
  366.     glPopMatrix();
  367.  
  368.     /* x-z plane, translate high */
  369.     glPushMatrix();
  370.     glRotatef(90, 1.0, 0.0, 0.0);
  371.     glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy - CUBESIDE);
  372.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  373.     draw_hexplane();
  374.     glPopMatrix();
  375.  
  376.     glColor3f(0.2, 0.6, 0.2);
  377.     /* y-z plane, translate low */
  378.     glPushMatrix();
  379.     glRotatef(90, 0.0, 1.0, 0.0);
  380.     glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx + CUBESIDE);
  381.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  382.     draw_hexplane();
  383.     glPopMatrix();
  384.     
  385.     /* y-z plane, translate high */
  386.     glPushMatrix();
  387.     glRotatef (90, 0.0, 1.0, 0.0);
  388.     glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx - CUBESIDE);
  389.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  390.     draw_hexplane();
  391.     glPopMatrix();
  392.  
  393.     glFlush();
  394.     glDepthMask(GL_TRUE);
  395.     glEnable(GL_DEPTH_TEST);
  396. }
  397.  
  398. float hex_data[8][3] =  {
  399.     {0., 0., 0.},
  400.     {1.155, 0., 0.},
  401.     {0.577, 1., 0.},
  402.     {-0.577, 1., 0.},
  403.     {-1.155, 0., 0.},
  404.     {-0.577, -1., 0.},
  405.     {0.577, -1., 0.},
  406.     {1.155, 0., 0.},
  407. };
  408.  
  409. /* draws a hexagon 2 units across, in the x-y plane, */
  410. /* centered at <0, 0, 0> */
  411.  
  412. void draw_hexagon(void)
  413. {
  414.     if(wflag) {
  415.     glPushMatrix();
  416.     glRotatef(a, 0.0, 0.0, 1.0);
  417.     }
  418.  
  419.     glBegin(GL_TRIANGLE_FAN);
  420.     glVertex3fv(hex_data[0]);
  421.     glVertex3fv(hex_data[1]);
  422.     glVertex3fv(hex_data[2]);
  423.     glVertex3fv(hex_data[3]);
  424.     glVertex3fv(hex_data[4]);
  425.     glVertex3fv(hex_data[5]);
  426.     glVertex3fv(hex_data[6]);
  427.     glVertex3fv(hex_data[7]);
  428.     glEnd();
  429.  
  430.     if(wflag)
  431.     glPopMatrix();
  432. }
  433.  
  434. void tmp_draw_hexplane(void)
  435. {
  436.     glRectf(-2.0, -2.0, 2.0, 2.0);
  437. }
  438.  
  439. /* draw 7 hexagons */
  440. void draw_hexplane(void)
  441. {
  442.     if(wflag) {
  443.     glPushMatrix();
  444.     glRotatef(-0.5*a, 0.0, 0.0, 1.0);
  445.     }
  446.  
  447.     /* center , <0, 0, 0> */
  448.     draw_hexagon();
  449.  
  450.     /* 12 o'clock, <0, 4, 0> */
  451.     glTranslatef(0., 4., 0.);
  452.     draw_hexagon();
  453.  
  454.     /* 10 o'clock, <-3.464, 2, 0> */
  455.     glTranslatef(-3.464, -2., 0.);
  456.     draw_hexagon();
  457.  
  458.     /* 8 o'clock, <-3.464, -2, 0> */
  459.     glTranslatef(0., -4., 0.);
  460.     draw_hexagon();
  461.  
  462.     /* 6 o'clock, <0, -4, 0> */
  463.     glTranslatef(3.464, -2., 0.);
  464.     draw_hexagon();
  465.  
  466.     /* 4 o'clock, <3.464, -2, 0> */
  467.     glTranslatef(3.464, 2., 0.);
  468.     draw_hexagon();
  469.  
  470.     /* 2 o'clock, <3.464, 2, 0> */
  471.     glTranslatef(0., 4., 0.);
  472.     draw_hexagon();
  473.  
  474.     if(wflag)
  475.     glPopMatrix();
  476. }
  477.  
  478. void sphdraw(float args[3])
  479. {
  480.     glPushMatrix();
  481.     glTranslatef(args[0], args[1], args[2]);
  482.     glCallList(asphere);
  483.     glPopMatrix();
  484. }
  485.  
  486. void setPerspective(int angle, float aspect, float zNear, float zFar)
  487. {
  488.     glPushAttrib(GL_TRANSFORM_BIT);
  489.     glMatrixMode(GL_PROJECTION);
  490.     gluPerspective(angle * 0.1, aspect, zNear, zFar);
  491.     glPopAttrib();
  492. }
  493.  
  494. /* initialize global 3-vectors */
  495. void init_3d(void)
  496. {
  497.     (void)srand48((long)time((time_t*)NULL));
  498.  
  499.     /* initialize colored points */
  500.     rv[0][0] = (float)drand48() * 10.;
  501.     rv[0][1] = (float)drand48() * 10.;
  502.     rv[0][2] = (float)drand48() * 10. - 10.;
  503.  
  504.     bv[0][0] = rv[0][0] + (float)drand48()*5.;
  505.     bv[0][1] = rv[0][1] + (float)drand48()*5.;
  506.     bv[0][0] = rv[0][2] + (float)drand48()*5.;
  507.  
  508.     gv[0][0] = rv[0][0] + (float)drand48()*5.;
  509.     gv[0][1] = rv[0][1] + (float)drand48()*5.;
  510.     gv[0][0] = rv[0][2] + (float)drand48()*5.;
  511.  
  512.     yv[0][0] = rv[0][0] + (float)drand48()*5.;
  513.     yv[0][1] = rv[0][1] + (float)drand48()*5.;
  514.     yv[0][0] = rv[0][2] + (float)drand48()*5.;
  515.  
  516.     mv[0][0] = rv[0][0] + (float)drand48()*5.;
  517.     mv[0][1] = rv[0][1] + (float)drand48()*5.;
  518.     mv[0][0] = rv[0][2] + (float)drand48()*5.;
  519.  
  520.     /* initialize eye velocity */
  521.     eyev[0] = eyev[1] = eyev[2] = 0.;
  522. }
  523.  
  524.  
  525. void init_graphics(void)
  526. {
  527.     int width = 600;
  528.     int height = 600;
  529.  
  530.     xmax = width;
  531.     ymax = height;
  532.     glDrawBuffer(GL_BACK);
  533.     glEnable(GL_DEPTH_TEST);
  534.     glClearColor(0.0, 0.0, 0.0, 0.0);
  535.     glClearDepth(1.0);
  536.  
  537.     glEnable(GL_CULL_FACE);
  538.     glCullFace(GL_BACK);
  539.  
  540.     glViewport(0, 0, xmax, ymax);
  541.     setPerspective(fovy, (float)xmax/(float)ymax, 0.01, farplane);
  542.     quadObj = gluNewQuadric();
  543.     gluQuadricNormals(quadObj, GLU_NONE);
  544.     asphere = glGenLists(1);
  545.     glNewList(asphere, GL_COMPILE);
  546.     gluSphere(quadObj, 0.3, 12, 8);
  547.     glEndList();
  548. }
  549.  
  550. extern char *optarg;
  551. extern int optind, opterr;
  552.  
  553. #define USAGE "usage message: this space for rent\n"
  554. void parse_args(int argc, char **argv)
  555. {
  556.     int c;
  557.  
  558.     hexflag = sflag = fflag = wflag = gflag = debug = FALSE;
  559.     opterr = 0;
  560.  
  561.     while( (c = getopt(argc, argv, "Xhixs:f:w:g:")) != -1)
  562.     switch(c) {
  563.       case 'X':
  564.         debug = TRUE;
  565.         break;
  566.       case 'h':
  567.         print_usage(argv[0]);
  568.         exit(1);    
  569.       case 'i':
  570.         print_info();
  571.         exit(1);    
  572.       case 'x':
  573.         hexflag = TRUE;
  574.         farplane = 300.;
  575.         break;
  576.       case 's':
  577.         sflag = TRUE;
  578.         speed = atoi(optarg);
  579.         if(speed < 0) {
  580.         fprintf(stderr, "Use a small positive value for speed ('s').\n");
  581.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  582.         exit(1);
  583.         }
  584.         break;
  585.       case 'f':
  586.         fflag = TRUE;
  587.         frame = atoi(optarg);
  588.         if(frame < 0) {
  589.         fprintf(stderr, "Try a small positive value for \n");
  590.         fprintf(stderr, "'f'; this is the number of vertical ");
  591.         fprintf(stderr, "retraces per redraw\n");
  592.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  593.         exit(1);
  594.         }
  595.         break;
  596.       case 'w':
  597.         wflag = TRUE;
  598.         da = atof(optarg);
  599.         if(da > 10.) {
  600.         fprintf(stderr, "That's a large rotational velocity ('w')");
  601.         fprintf(stderr, " but you asked for it\n");
  602.         }
  603.         break;
  604.       case 'g':
  605.         gflag = TRUE;
  606.         gravity = atof(optarg);
  607.         if(gravity <= 0) {
  608.         fprintf(stderr, "Gravity ('g') should be positive\n");
  609.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  610.         }
  611.         break;
  612.       case '?':
  613.         fprintf(stderr, USAGE);
  614.     }
  615.  
  616.     /* set up default values */
  617.     if(!sflag)
  618.     speed = 3;
  619.     if(!fflag)
  620.     frame = 2;    
  621.     if(!wflag)
  622.     da = 0.;
  623.     if(!gflag)
  624.     gravity = G;
  625. }
  626.  
  627. void print_usage(char *program)
  628. {
  629. printf("\nUsage: %s [-h] [-i] [-x] [-s speed]", program);
  630. printf(" [-w rot_v] [-g gravity]\n\n");
  631. printf("-h              Print this message.\n");
  632. printf("-i              Print information about the demo.\n");
  633. printf("-x              Enclose the particles in a box made of hexagons.\n");
  634. printf("-s speed        Sets the number of new line segments per redraw \n");
  635. printf("                interval per line. Default value: 3.\n");
  636.  
  637. /*** The X port does not currently include a timer, so this feature is disabled.
  638. printf("-f framenoise   Sets the number of vertical retraces per redraw\n");
  639. printf("                interval. Example: -f 2 specifies one redraw per\n");
  640. printf("                2 vertical retraces, or 30 frames per second.\n");
  641. printf("                Default value: 2.\n");
  642. ************/
  643.  
  644. printf("-w rot_v        Spins the hexagons on their centers, and the sides\n");
  645. printf("                of the box on their centers. Hexagons spin at the\n");
  646. printf("                rate rot_v degrees per redraw, and box sides spin\n");
  647. printf("                at -rot_v/2 degrees per redraw.\n");
  648. printf("-g gravity      Sets the strength of the attraction of the eye to\n");
  649. printf("                the red particle. Actually, it's not gravity since\n");
  650. printf("                the attraction is proportionate to distance.\n");
  651. printf("                Default value: 0.002. Try large values!\n");
  652. /* input added for GLX port */
  653. printf(" Executions control:  \n");
  654. printf("    <spacebar>    step through single frames\n");
  655. printf("    g        begin continuous frames\n");
  656. printf("    s        stop continuous frames\n");
  657.  
  658. }
  659.  
  660. void print_info(void)
  661. {
  662. printf("\nLORENZ ATTRACTOR DEMO\n\n");
  663. printf("This program shows some particles stuck in a Lorenz attractor (the \n");
  664. printf("parameters used are r=28, b=8/3, sigma=10). The eye is attracted to \n");
  665. printf("the red particle, with a force directly proportional to distance. \n");
  666. printf("A command line argument puts the particles inside a box made of hexagons, \n");
  667. printf("helping  to maintain the sense of 3 dimensions, but it can slow things down.\n");
  668. printf("Other options allow you to play with the redraw rate and gravity.\n\n");
  669.  
  670. printf("Try lorenz -h for the usage message.\n");
  671. }
  672.